package cn.iocoder.boot.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.vladsch.flexmark.ext.tables.*;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.ast.NodeVisitor;
import com.vladsch.flexmark.util.ast.VisitHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class TableVisitor {
    // 自定义表格处理器
    private final NodeVisitor visitor;
    private List<List<String>> tbData;

    public TableVisitor() {
        // 注册表格处理器
        visitor = new NodeVisitor(
                new VisitHandler<>(TableBlock.class, this::visitTable)
        );
    }

    public List<List<String>> getTbData() {
        return tbData;
    }

    /**
     * 此方法有时未进入，需检查document传入是否为正确的markdown格式
     *
     * @param table
     */
    // 处理表格
    private void visitTable(TableBlock table) {
        List<List<String>> tableData = new ArrayList<>();

        // 遍历表格子节点（表头、表体）
        for (Node child : table.getChildren()) {
            if (child instanceof TableHead) {
                // 表头行
                TableRow headerRow = (TableRow) child.getFirstChild();
                List<String> headers = extractRowData(headerRow);
                tableData.add(headers);
            } else if (child instanceof TableBody) {
                // 表体行
                for (Node rowNode : child.getChildren()) {
                    if (rowNode instanceof TableRow) {
                        List<String> rowData = extractRowData((TableRow) rowNode);
                        tableData.add(rowData);
                    }
                }
            }
        }
        tbData = tableData;
//        log.info("markdown解析发现表格:{}", tableData);
        // 打印表格数据
//            System.out.println("发现表格:");
//            for (List<String> row : tableData) {
//                System.out.println(row);
////                System.out.println(String.join(" | ", row));
//            }
    }

    // 提取行数据
    private List<String> extractRowData(TableRow row) {
        List<String> rowData = new ArrayList<>();
        for (Node cellNode : row.getChildren()) {
            if (cellNode instanceof TableCell) {
                // 提取单元格文本
                String cellText = cellNode.getChars().toString().trim();
                rowData.add(cellText);
            }
        }
        return rowData;
    }

    public void process(Node document) {
        visitor.visit(document);
    }

    /**
     * 浮点数转整数,markdown表格数据中，用量等整数型数据经常带有.0 小数，转换为整数输出
     *
     * @param cellText
     * @return
     */
    private String double2IntStr(String cellText) {
        if (cellText.endsWith("0") && cellText.contains(".")) {
            try {
                // 解析字符串为浮点数
                double doubleValue = Double.parseDouble(cellText);
                // 转换为整数
                int intValue = (int) doubleValue;
                return String.valueOf(intValue);
            } catch (NumberFormatException e) {
                return cellText;
            }
        } else {
            return cellText;
        }
    }

    /**
     * markdown表格转json
     *
     * @return
     */
    public JSONArray mdDataToJson() {
        if (tbData == null || tbData.isEmpty()) {
            log.error("markdown源数据解析为空");
            return null;
        }
        // 取表头
        List<String> headers = tbData.get(0);
        int maxCols = headers.size() + 3; // 往右找3列，超出部分不管了
        // 有可能存在数据行列数大于表头列数，取最大列数
        int maxCols1 = tbData.stream().mapToInt(List::size).max().orElse(0);  // 有误差，很多空列也算在内了
        if (maxCols1 < maxCols) {
            maxCols = maxCols1;
        }
        JSONArray jsonArray = new JSONArray();
        for (int i = 1; i < tbData.size(); i++) {
            JSONObject jsonObject = new JSONObject();
            List<String> rowData = tbData.get(i);
//            for (int j = 0; j < headers.size(); j++) {
            for (int j = 0; j < maxCols; j++) {
//                String header = headers.get(j).replace("|", "").replace(" ", "");
//                String cellText = rowData.get(j).replace("|", "").replace(" ", "");
//                rowData.forEach(System.out::println);
                String header = "";
                if (j >= headers.size()) { // 数据行列超出表头列数，补充列头
//                    log.info("数据行列数超出表头列数，补充列头:{}", j+1);
                    header = "Unnamed" + (j + 1);
                } else {
                    header = headers.get(j).replace("| ", "").replace(" |", "");
                }
                String cellText = "";
                if(j <= rowData.size() - 1) {
                    cellText = rowData.get(j).replace("| ", "").replace(" |", "");
                } else { // 数据行列数小于表头列数或最大数据行列数
                    String aa = "";
                    // 遍历rowData
                    for (String cell : rowData) {
                        aa = aa + cell;
                    }
//                    log.info("rowData列数异常:"+aa+" / " + rowData.size());
                }
                String cellText1 = double2IntStr(cellText.replace("\\|", "")); //当前值
                if (!"NaN".equals(jsonObject.getStr(header.trim(), "NaN")) && "NaN".equals(cellText1)) { // 防止字段名重复覆盖
                    continue;
                }
                jsonObject.put(header.trim(), cellText1);
            }
            // 用"序号"字段非空非数识别 合并单元格的空行问题.除序号列其它都为空 BM25030618798
            boolean allFieldsNaN = true;
            int validFieldCount = 0;
            for (String key : jsonObject.keySet()) {
                if (!key.equals("序号") && !key.startsWith("Unnamed")) {
                    if (!StrUtil.isBlank(jsonObject.getStr(key)) && !"NaN".equals(jsonObject.getStr(key))) {
                        allFieldsNaN = false;
                        break;
                    }
                }
                // 检测到某行有效字段数小于等于2，则丢弃。若把位号删除，则合并列号失效了
//                if (!StrUtil.isBlank(jsonObject.getStr(key)) && !"NaN".equals(jsonObject.getStr(key))) {
//                    validFieldCount++;
//                }
            }
            if (!allFieldsNaN) { // && validFieldCount > 2
                jsonArray.put(jsonObject);
            }
        }
        return jsonArray;
    }

    /**
     * markdown有多sheet页，取第一列
     *
     * @param document
     * @return
     */
//    public List<Node> extractSheets(Node document) {
//        List<Node> sheets = new ArrayList<>();
//        Node currentNode = document.getFirstChild();
//        while (currentNode != null) {
//            if (currentNode instanceof Heading && ((Heading) currentNode).getLevel() == 2) {
//                sheets.add(currentNode);
//            }
//            currentNode = currentNode.getNext();
//        }
//        return sheets;
//    }

}